\f0\b0\i0\outl0\shad0\fs20 \cf0 \expan0 \ul0 tr parameter (NIL).\line 42: 3F2C 0058 '?,.X' PUSH 88(A4)\line iovRefNum parameter.\line 46: 4EBA 0BAE 1000BF6 JSR FlushVol\line If a volume is available, flush it.\line 4A: 3C1F '<.' POP D6\line Pop off error code.\line \'0C 4C: 206D FEC8 -$138 lab_3 MOVEA.L glob49(A5),A0\line Now do the same thing with the right list box.\line 50: 2850 '(P' MOVEA.L (A0),A4\line 52: 4A6C 0058 'Jl.X' TST 88(A4)\line 56: 670E 1000066 BEQ.S lab_4\line 58: 4267 'Bg' CLR -(A7)\line 5A: 42A7 'B.' CLR.L -(A7)\line 5C: 3F2C 0058 '?,.X' PUSH 88(A4)\line 60: 4EBA 0B94 1000BF6 JSR FlushVol\line 64: 3C1F '<.' POP D6\line \line Lets take a quick look and FlushVol and we can see a couple of things. Fist of all, we can quickly see what the parameters are: Parm1 is a pointer to the Volume Name, Parm2 is the Volume Ref Number. Looking back at MainEven, we see that the PEA 88(A4) is referring to the Volume Reference Number. FlushVol "writes the contents of the associated volume buffer and descriptive informatin about the volume (if they've changed since the last time FlushVol was called)." [IM II pg 89]. The returned result of this procedure is the OSErr.\line \line ;-refs - 1/MAINEVEN 2/FLUSHRES 2/REMOVEST \line \line BF6: 4E56 FFC0 'NV..' FlushVol LINK A6,#-$40\line BFA: 41EE FFC0 200FFC0 LEA vbu_1(A6),A0\line BFE: 316E 0008 0016 2000008 MOVE param2(A6),ioVRefNum(A0)\line C04: 216E 000A 0012 200000A MOVE.L param1(A6),ioNamePtr(A0)\line C0A: A013 '..' _FlushVol ; (A0|IOPB:ParamBlockRec):D0\\OSErr \line C0C: 3D40 000E 200000E MOVE D0,funRslt(A6)\line C10: 4E5E 'N^' UNLK A6\line C12: 225F '"_' POP.L A1\line C14: 5C8F '\\.' ADDQ.L #6,A7\line C16: 4ED1 'N.' JMP (A1)\line \line \line back to MainEven\line \line 66: 4EAD 020A 2005DCA lab_4 JSR HANDLEBU(A5)\line 6A: 486D 0212 2005EF8 PEA MYFILTER(A5)\line 6E: 486E FFFA 200FFFA PEA vab_1(A6)\line 72: A991 '..' _ModalDialog ; (filterProc:ProcPtr; VAR itemHit:INTEGER) \line ModalDialog is the all-purpose dialog handler. It will monitor events and wait for an event involving an active dialog item. Upon returning, the dialog item number is returned in ModalDialog's 2nd parameter - in this case, vab_1. Once the trap returns, the program has to figure out what to do now that an item has been activated. Below, is a simple jump table that repeatedly subtracts integers from vab_1 until it is zero, at which point the program knows that it has the proper dialog item. It then branches to the appropriate routine.\line ModalDialog also takes a parameter that specifies a special procedure that it can call whenever an event occurs. What that means, is that the line PEA MYFILTER is telling ModalDialog to execute the procedure MYFILTER anytime an event occurs. We can take a look at MYFILTER to see what it is doing (although in cracking, we probably don't care). Right now I will guess that MYFILTER is taking care of things like allowing multiple selections in the list boxes,. displaying the font string, and displaying the size of the selection.\line 74: 302E FFFA 200FFFA MOVE vab_1(A6),D0\line 78: 5540 'U@' SUBQ #2,D0\line Copy button.\line 7A: 6736 10000B2 BEQ.S lab_7\line 7C: 5340 'S@' SUBQ #1,D0\line Remove Button.\line 7E: 672C 10000AC BEQ.S lab_6\line 80: 5340 'S@' SUBQ #1,D0\line Help Button.\line 82: 6734 10000B8 BEQ.S lab_8\line 84: 5340 'S@' SUBQ #1,D0\line Quit Button.\line 86: 6720 10000A8 BEQ.S lab_5\line 88: 5340 'S@' SUBQ #1,D0\line Left Open/Close Button.\line 8A: 673C 10000C8 BEQ.S lab_10\line 8C: 5340 'S@' SUBQ #1,D0\line Right Open/Close Button.\line 8E: 6742 10000D2 BEQ.S lab_11\line 90: 5340 'S@' SUBQ #1,D0\line Font Radio Button.\line 92: 672A 10000BE BEQ.S lab_9\line 94: 5340 'S@' SUBQ #1,D0\line DA Radio Button.\line 96: 6726 10000BE BEQ.S lab_9\line 98: 5340 'S@' SUBQ #1,D0\line Left List Box.\line 9A: 6740 10000DC BEQ.S lab_12\line 9C: 5340 'S@' SUBQ #1,D0\line Right List Box.\line 9E: 674A 10000EA BEQ.S lab_13\line A0: 0440 0028 '.@.(' SUBI #40,D0\line We will have to check MyFilter to see what this is doing.\line A4: 6752 10000F8 BEQ.S lab_14\line A6: 6058 1000100 BRA.S lab_15\line A8: 7E01 '~.' lab_5 MOVEQ #1,D7\line User hit Quit, so disable the loop and jump to the loop end.\line AA: 6054 1000100 BRA.S lab_15\line AC: 4EAD 01E2 2004E98 lab_6 JSR REMOVEST(A5)\line Remove Button.\line B0: 604E 1000100 BRA.S lab_15\line B2: 4EAD 01EA 2004F5C lab_7 JSR COPYSTUF(A5)\line Copy Button.\line B6: 6048 1000100 BRA.S lab_15\line B8: 4EAD 023A 2006B0E lab_8 JSR DOHELP(A5)\line Help Button.\line BC: 6042 1000100 BRA.S lab_15\line BE: 3F2E FFFA 200FFFA lab_9 PUSH vab_1(A6)\line Push the selected item number,\line C2: 4EAD 022A 20064F2 JSR SELCLICK(A5)\line and change to either Fonts or DAs.\line C6: 6038 1000100 BRA.S lab_15\line C8: 2F2D FEC4 -$13C lab_10 PUSH.L glob48(A5)\line CC: 4EAD 0242 2006B50 JSR DOCFILE(A5)\line Left Open (or close) Button.\line D0: 602E 1000100 BRA.S lab_15\line D2: 2F2D FEC8 -$138 lab_11 PUSH.L glob49(A5)\line D6: 4EAD 0242 2006B50 JSR DOCFILE(A5)\line Right Open (or close) Button.\line DA: 6024 1000100 BRA.S lab_15\line DC: 2F2D FEC4 -$13C lab_12 PUSH.L glob48(A5)\line Remember this guy? Refers to the left box.\line E0: 2F2D FFE8 -$18 PUSH.L glob62(A5)\line E4: 4EAD 0202 2005CB8 JSR CONTENTC(A5)\line Handle a list box click.\line E8: 6016 1000100 BRA.S lab_15\line EA: 2F2D FEC8 -$138 lab_13 PUSH.L glob49(A5)\line Refers to the right list box.\line EE: 2F2D FFE8 -$18 PUSH.L glob62(A5)\line F2: 4EAD 0202 2005CB8 JSR CONTENTC(A5)\line List box handler.\line F6: 6008 1000100 BRA.S lab_15\line F8: 3F2D FEDC -$124 lab_14 PUSH glob55(A5)\line FC: 4EAD 0232 2006A6A JSR HANDLEIN(A5)\line 100: 1007 '..' lab_15 MOVE.B D7,D0\line Here is the end of the main loop. This checks to see if the loop should terminate. If not, branch back to the beginning of the loop.\line 102: 6700 FF06 100000A BEQ lab_1\line 106: 4CDF 10C0 'L...' MOVEM.L (A7)+,D6-D7/A4\line At this point, either an error occurred or the user has hit the Quit button.\line 10A: 4E5E 'N^' UNLK A6\line 10C: 4E75 'Nu' RTS \line \line 10E: CD41 494E 4556 454E data1 DNAME MAINEVEN,0,0\line HANDLEBU Procedure\line 5DCA: QUAL HANDLEBU ; b# =501 s#2 =proc214\line \line vid_1 VEQU -272\line vid_2 VEQU -256\line 5DCA: VEND \line \line A quick observation here. After scanning the first few lines, you can notice some hereto unknown things. Look at the references to glob50. At this point, we know that globs 48 and 49 have been set up to refer (we don't know exactly how) to the two list boxes in the main dialog. A quick look down a ways reveals that D7 is used to pass an integer to our DrawString procedure (proc5). If we assume that D7 is the ID # of the STR# resource (since this is the parameter that proc5 requires), then that MOVEQ 1,D7 (line 5) must refer to STR# 1 which reads "Copy". The next two strings in the resource are "<<Copy<<" and ">>Copy>>" which are exactly the three strings that the copy button on the dialog can contain. So we might assume right now that glob50 refers to one of the list boxes, and can be used to determine whether the user has selected an item(s) in the list box. Based upon this information, the procedure will fill in the copy button with the proper string.\line \line ;-refs - 1/MAINEVEN \line \line 5DCA: 4E56 FEEE 'NV..' HANDLEBU LINK A6,#-$112\line 5DCE: 48E7 0308 'H...' MOVEM.L D6-D7/A4,-(A7)\line 5DD2: 4AAD FECC -$134 TST.L glob50(A5)\line Check the list box (it seems)\line 5DD6: 660C 2005DE4 BNE.S lid_1\line Look at what this branch is skipping.\line 5DD8: 7E01 '~.' MOVEQ #1,D7\line The string is "Copy".\line 5DDA: 3F3C 0003 '?<..' PUSH #3\line DIMITEM needs the item number to dim as a parm. Item 3 is the Remove button.\line 5DDE: 4EBA A308 20000E8 JSR DIMITEM\line Take a quick look at DIMITEM and you will see that it takes an item number as a parameter, pushes the parameter, then pushes the number -1 (255 if we are talking about signed numbers) and calls HILITEIT which uses the 2nd parameter to either set or dim the desired button.\line 5DE2: 607A 2005E5E BRA.S lid_8\line The Remove button is dimmed anytime there is no selection in one of the list boxes. How did this procedure know there was no selection? It checked to see if glob50 was blank (or possible a NIL pointer) and if so, there is no selection.\line 5DE4: 202D FECC -$134 lid_1 MOVE.L glob50(A5),D0\line Here is the real key. glob50 is being compared to glob48. We know glob48 has something to do with the left list box, and look what happens if they are the same...D7 gets 3 which means string">>Copy>>" - the user has made a selection in the left list box.\line 5DE8: B0AD FEC4 -$13C CMP.L glob48(A5),D0\line 5DEC: 6604 2005DF2 BNE.S lid_2\line 5DEE: 7E03 '~.' MOVEQ #3,D7\line 5DF0: 6002 2005DF4 BRA.S lid_3\line 5DF2: 7E02 '~.' lid_2 MOVEQ #2,D7\line Otherwise the user has made a selection in the right list box. A quick note: glob50 was not compared to glob49, but it was compared to glob48. We can deduce from this that glob50 had to contain either glob48 or glob49. What this means is that glob50 seems to indicate that something has been selected in one of the list boxes or is empty if there is no selection.\line 5DF4: 206D FECC -$134 lid_3 MOVEA.L glob50(A5),A0\line This is a mess. We know that glob50 is a handle to a host of information about one of the list boxes, but we didn't bother to figure which bytes mean what. The best thing to do here is to analyze all the branches in the mess, see where they go, and look at what happens as a result of each branch. So...\line 5DF8: 2050 ' P' MOVEA.L (A0),A0\line 5DFA: 2068 0004 ' h..' MOVEA.L 4(A0),A0\line 5DFE: 2050 ' P' MOVEA.L (A0),A0\line 5E00: 3C28 0058 '<(.X' MOVE 88(A0),D6\line Look familiar? Let's guess that this is a vRefNum for the list box containing the selection.\line 5E04: 206D FECC -$134 MOVEA.L glob50(A5),A0\line 5E08: 2050 ' P' MOVEA.L (A0),A0\line 5E0A: 2068 0004 ' h..' MOVEA.L 4(A0),A0\line 5E0E: 2050 ' P' MOVEA.L (A0),A0\line 5E10: 4A68 0056 'Jh.V' TST 86(A0)\line 5E14: 6C02 2005E18 BGE.S lid_4\line OK, here is a branch. If it executes, D6 has something (which we guessed to be a vRefNum) in it which gets passed on to lid_4.\line 5E16: 4246 'BF' CLR D6\line Otherewise, D6 is zeroed (no volume available).\line 5E18: 4A46 'JF' lid_4 TST D6\line 5E1A: 57C0 'W.' SEQ D0\line D0=FF hex if there is no volume.\line 5E1C: 4A00 'J.' TST.B D0\line 5E1E: 6616 2005E36 BNE.S lid_5\line This branch executes if D6 was zero and will cause 1 to moved into D7 - "Copy".\line 5E20: 2F00 '/.' PUSH.L D0\line Save D0 on the stack (not a parameter)\line 5E22: 4267 'Bg' CLR -(A7)\line Create space on the stack for the return value.\line 5E24: 3F06 '?.' PUSH D6\line Aha! We were right. proc6 needs a vRefNum and here is good old D6 being pushed as a parm. D6 is indeed the vRefNum.\line 5E26: 4EAD 0032 10004CA JSR proc6(A5)\line Takes a vRefNum as a parm, then does a GetVolInfo, and checks the iovAttributes to see if the disk is locked. Returns a 1 if locked, 0 if unlocked.\line 5E2A: 121F '..' POP.B D1\line Pop off the locked status.\line 5E2C: 201F ' .' POP.L D0\line Pop off the original D0.\line 5E2E: 8001 '..' OR.B D1,D0\line Or them so that, in effect, the AND instruction below will be ANDing both D0 and D1 with 1.\line 5E30: 0240 0001 '.@..' ANDI #1,D0\line Check to see if one of the two contains a non-zero value,\line 5E34: 6702 2005E38 BEQ.S lid_6\line and if so, do not put a 1 in D7 (the string is not "Copy").\line 5E36: 7E01 '~.' lid_5 MOVEQ #1,D7\line String is "Copy" (meaning that DA Mover will not allow the Copy to proceed) and from the above code, we might guess that this is a result of the destination volume being locked so copying is impossible.\line 5E38: 4267 'Bg' lid_6 CLR -(A7)\line 5E3A: 206D FECC -$134 MOVEA.L glob50(A5),A0\line And here is basically the same as above except that the other list box's volume is being checked\line 5E3E: 2050 ' P' MOVEA.L (A0),A0\line 5E40: 3F28 0058 '?(.X' PUSH 88(A0)\line Push the vRefNum of the volume from which the selection has been made.\line 5E44: 4EAD 0032 10004CA JSR proc6(A5)\line Locked Volume?\line 5E48: 101F '..' POP.B D0\line 5E4A: 670A 2005E56 BEQ.S lid_7\line Go if not locked.\line 5E4C: 3F3C 0003 '?<..' PUSH #3\line If the volume is locked, we cannot remove anything so dim the Remove Button.\line 5E50: 4EBA A296 20000E8 JSR DIMITEM\line 5E54: 6008 2005E5E BRA.S lid_8\line 5E56: 3F3C 0003 '?<..' lid_7 PUSH #3\line Else activate the Remove Button (volume is not locked).\line 5E5A: 4EBA A2AE 200010A JSR UNDIMITE\line \line OK, let's re-cap for a minute. If you look back at MakeAWin, you will note that glob48 and glob49 are set up to refer to information about the left and right list boxes respectively. We also know that these globs contain information about the volume (and possibly the file) that is being displayed in the list boxes - since 88 bytes off the start of the pointer is the volume reference number. The above code can be broken into two pieces: from line 5DF4, to lid_5 and from lid_6 to one line past lid_7. The first piece is messy, but the end result is that the destination volume is tested to see if it is locked, and if so, the copy button text is set to "Copy". Therefore we can now assume that all that messy stuff beforehand was in essence setting a pointer to the destination list box information. Remember from MakeAWin there was a strange section of code that seemed to link the two globs to each other? Well, now we see that glob50 is set to one of these two (the one that contains a selection) but glob50 must also be able to access the other list box's volume to see if it is locked (or to see if copying to it is possible). The second section checks to see if the volume containing the selection is locked, and if so, Removing is not possible.\line 5E5E: BE6D FFF4 -$C lid_8 CMP.W glob65(A5),D7\line Once again, we don't know what this glob means, but we can see what gets skipped if the branch executes. Once we know what gets skipped, we have a decent idea what the global means. Keep in mind that the global is being compared to D7 - the string resource ID #.\line 5E62: 6700 0082 2005EE6 BEQ lid_13\line So if glob65 contains the ID # in D7, skip to the end of the procedure.\line 5E66: 42A7 'B.' CLR.L -(A7)\line 5E68: A8D8 '..' _NewRgn ; :RgnHandle \line 5E6A: 285F '(_' POP.L A4\line 5E6C: 2F0C '/.' PUSH.L A4\line 5E6E: A87A '.z' _GetClip ; (rgn:RgnHandle) \line 5E70: 486E FEF0 200FEF0 PEA vid_1(A6)\line 5E74: 42A7 'B.' CLR.L -(A7)\line 5E76: 42A7 'B.' CLR.L -(A7)\line 5E78: A8A7 '..' _SetRect ; (VAR r:Rect; left,top,right,bottom:INTEGER) \line 5E7A: 486E FEF0 200FEF0 PEA vid_1(A6)\line 5E7E: A87B '.{' _ClipRect ; (r:Rect) \line 5E80: 486E FF00 200FF00 PEA vid_2(A6)\line 5E84: 3F07 '?.' PUSH D7\line 5E86: 4EAD 002A 100048C JSR proc5(A5)\line Once again, the DrawString procedure. D7 is the string # and vid_2 returns a pointer to the string.\line 5E8A: 2F2D FFF6 -$A PUSH.L glob66(A5)\line Look at the trap below. glob66 HAS to be a CtlHdl (Handle to a control object on a dialog),\line 5E8E: 486E FF00 200FF00 PEA vid_2(A6)\line and vid_2 we already know has the string whose ID # is in D7. Since D7's string is "Copy", ">>Copy>>", or "<<Copy<<", we can assume that the control in question is the Copy Button.\line 5E92: A95F '._' _SetCTitle ; (Ctl:CtlHdl; title:Str255) \line \'0C 5E94: 3B47 FFF4 -$C MOVE D7,glob65(A5)\line Here is a clue! glob65 gets set to the string ID# - now this makes sense. Back up a few lines, glob65 was compared to D7 and if they were equal, all this stuff gets skipped. Now glob65 gets set to D7. It looks like the program is checking to see whether the Copy Button already has the correct string in it. If not, the above code changes it and updates glob65 to the new string ID# so that next time through the event loop, glob65 has the current ID # of the Copy Button's text.\line 5E98: 7001 'p.' MOVEQ #1,D0\line 5E9A: B047 '.G' CMP.W D7,D0\line Remember: if D7 is 1, the string is "Copy", and no copying is allowed - either because nothing is selected, or because the destination volume is locked.\line 5E9C: 660A 2005EA8 BNE.S lid_9\line If copying is to be allowed, then branch.\line 5E9E: 3F3C 0002 '?<..' PUSH #2\line Refers to the Copy Button:\line 5EA2: 4EBA A266 200010A JSR UNDIMITE\line and - wait a second. Notice that this is backward! It is dimming the copy button if copying is allowed! I'm not sure why it does this, but look down a few lines...\line 5EA6: 6008 2005EB0 BRA.S lid_10\line 5EA8: 3F3C 0002 '?<..' lid_9 PUSH #2\line 5EAC: 4EBA A23A 20000E8 JSR DIMITEM\line 5EB0: 2F0C '/.' lid_10 PUSH.L A4\line 5EB2: A879 '.y' _SetClip ; (rgn:RgnHandle) \line 5EB4: 2F0C '/.' PUSH.L A4\line 5EB6: A8D9 '..' _DisposRgn ; (rgn:RgnHandle) \line 5EB8: 7001 'p.' MOVEQ #1,D0\line Here we go. Now, if D7 is 1, dim the copy button, otherwise enable it.\line 5EBA: B047 '.G' CMP.W D7,D0\line 5EBC: 660A 2005EC8 BNE.S lid_11\line 5EBE: 3F3C 0002 '?<..' PUSH #2\line 5EC2: 4EBA A224 20000E8 JSR DIMITEM\line 5EC6: 6008 2005ED0 BRA.S lid_12\line 5EC8: 3F3C 0002 '?<..' lid_11 PUSH #2\line 5ECC: 4EBA A23C 200010A JSR UNDIMITE\line 5ED0: 206D FFF6 -$A lid_12 MOVEA.L glob66(A5),A0\line We already saw (from the SetCTitle trap above) that glob66 is a handle to the Copy button.\line 5ED4: 2050 ' P' MOVEA.L (A0),A0\line Convert the handle to a pointer.\line 5ED6: 43EE FEF0 200FEF0 LEA vid_1(A6),A1\line 5EDA: 5088 'P.' ADDQ.L #8,A0\line Well, according to IM, adding 8 bytes to a pointer to a control record makes the pointer point to the a window that the control is in.\line 5EDC: 22D8 '".' MOVE.L (A0)+,(A1)+\line So, move the WindowPtr to vid_1.\line 5EDE: 22D8 '".' MOVE.L (A0)+,(A1)+\line and now move the Rect (next parameter in a control record) into vid_1.\line 5EE0: 486E FEF0 200FEF0 PEA vid_1(A6)\line 5EE4: A92A '.*' _ValidRect ; (goodRect:Rect) \line This trap tells the Window Manager not to update the region Rect.\line 5EE6: 4CDF 10C0 'L...' lid_13 MOVEM.L (A7)+,D6-D7/A4\line And, now we are finished.\line 5EEA: 4E5E 'N^' UNLK A6\line 5EEC: 4E75 'Nu' RTS \line \line I am not sure exactly what is going on there when it sets the button to the opposite that it is supposed to be, then sets it properly. I might hazard a guess that this technique somehow gurrantees that the region will get redrawn properly, but I really don't know - nor do I really care, for that matter. It is pretty clear what this procedure does - it updates the text and active status of the various buttons on the main dialog. Once this is done, MainEven can let the user make a selection, act upon the selection, and then the whole thing starts over.\line \line 5EEE: C841 4E44 4C45 4255 data276 DNAME HANDLEBU,0,0\line \line Well, that wraps up the intensive assembly listing. Font/DA Mover has many more procedures, but the idea here was to look at an assembly listing and apply the stuff at the beginning of the tutorial to a real life situation and see if you can guess what is going on. Next I will discuss the use of TMON, and finally we will look at cracking a real application: Sorcerer. (I am choosing this because it is easy, and I recently cracked it so it is still failry fresh in my mind.)\line \'0CUsing TMON\line \line TMON, unlike Nosy, is a real-time monitor / debugger. We will be using TMON in several situations: to break into active dialog windows, to break into programs that Nosy won't decompile properly, or when Nosy produces such a massive listing that we need to trace the application to see what happens where. To install TMON, just drag the application and the init into the system folder and restart. The application can be launched to configure it, but you probably won't need to do this. If you do configure it, make sure you save the changes in a User Area in the System Folder.\line TMON can be entered several ways: System Errors, Debugger traps (this is a great technique for breaking into tough programs), user specified traps, and by pressing the interrupt button on the side of your Mac. If you lack the interrupt button, use the Programmer's Key init - this allows you to hold down command and option and press the startup key on an extended keyboard.\line Once in TMON, you are presented with a Menu bar and possibly some windows. A quick note about TMON windows. They can be resized and dragged only in the vertical directions. To change values in the various windows, click the insertion bar in front of the value to change and type right over the old value. Pressing Return chops off the line at the insertion bar, pressing Enter leaves the rest of the line as is. For example, lets say you are changing the address of a dump window. If it currently reads "Dump From 00000000" and you type 1234 over the first 4 values, you have two choices. Hitting Return at this point chops off the last 4 zeroes making the effective address 1234 hex. If you were to hit Enter instead, the remaining zeroes would remain making the effective address 12340000 hex. Here are what the various menu commands do:\line Dump / Cmd-d and Asmbly / Cmd-a\line Brings up either a dump window or an assembly window. The dump window lists hex and ascii codes for a block of memory and the assembly window disassembles memory. The first line allows you to specify where the window will start its listing: Dump (Assembly) From XXXXXXX where XXXXXXX is an effective address. You can move the insertion bar right into this line and type over whatever is there. You can enter an address directly, specify a register (and the window will start from the address contained in the register), or a register indirect (the window will start from the address in the register, but will remember the register address). Examples: Dump From:\line \line 1)\line 80FFCA\line Dump listing starts from the absolute address 80FFCA hex. If you scroll the window, the displayed address will change to the address of the first line in the listing.\line \line )2\line A5\line \line Dump starts from the address contained in register A5. The address displayed on the Dump From line will be replaced with the address in register A5. If you scroll, the displayed address will again change to reflect the first line in the listing, and if A5 changes, the window will not change.\line \line 3)\line 0(A1)\line \line Dump starts from the address in A1 plus zero (in this case). The displayed address on the Dump From line does not change to the address in A1, rather it now displays 00000000(A1) indicating that the listing is anchored to the register. As you scroll, the zeroes will change to reflect how many bytes from the address in A1 the first line in the listing is - also, if A1 changes, the window will automatically change to the new value of A1.\line The most common entry for an assembly window is 0(PC) which says to disassemble from the program counter. Then as you step through the program, the window automatically scrolls so that the first line is where the program counter is. The windows list - from left to right - the address, any registers that contain that address (Note the P - for program counter - next to the first line when you disassemble from 0(PC) ), the resource the listing comes from if any (assembly window only), and then either hex and ascii bytes, or disassembled instructions. In addition, the assembly window will display comments to the right, indicating the destination of branches. Additional dump windows can be activated by holding down Shift while clicking on Dump in the menu bar - this is the only display that can have multiple windows. You will find if handy to have, in addition to the dissambly window, a dump window anchored to the A7 register (so make the Dump From read 0(A7) ) so that you can quickly see what addresses are being pushed on the stack. If you need to see what the actual data of these addresses are, just shift-click Dump to bring up successive dump windows, and make each window dump from successive addressess (4 bytes each) on the stack. Remember that the stack moves backwards, so the first thing pushed on the stack will be to the right (in the dump window) of the second thing pushed on the stack, etc.\line Brkpts / Cmd-b\line Allows the setting of up to eight breakpoints. Simply enter the address of the breakpoint into one of the 8 slots. To remove a breakpoint, type a hyphen for the first digit of the address to remove and hit return. Breakpoints cause TMON to halt execution of the application at the address of the breakpoint. I generally use breakpoints to skip out of long loops. For example, if you are stepping through a section of code and you find a DBRA loop (usually moving a section of data) where the data register has some god-awful value like 63 (often used to move strings), enter a breakpoint at the address of the instruction immediately after the DBRA and then exit. TMON will break execution after the loop has finished.\line Regs / Cmd-r\line Displays the 16 registers, PC, and status flags, any of which can be modified by typing right over the current values. The flags are displayed as the letter that I have been using - C for Carry, Z for Zero, etc. When the letter is capitalized, the flag is set. To change the value of the flag, simply change the capitalization.\line Heap / Cmd-h\line Displays memory blocks in the application heap zone. Basically this window lists all allocated blocks of memory in the applications heap zone (in the form of the pointers to the blocks), the size of the block, a digit that is meaningless to me, and the blocks status - either 1) Free, not allocated to anything yet, 2) Nonrel, non-relocatable, 3) Handle at ...., relocatable block with handle at the address specified, or 4) INVALID which means there is a big problem somewhere.\line File / Cmd-f\line Brings up a window listing all open resource files by file reference number. In most cases, the last number in the list refers to the System File. Entering a file reference number after the Resource file # prompt lists the files resources and where in memory they are. From left to right, the information displayed is: Resource type, Resource ID #, Attributes, location in memory. Attributes are as follows: R = System reference, H = Load into system heap, P = purgeable, L = locked, T = protected, 1 = pre-loaded (loaded at startup time), W = write into resource file. To return to a list of file reference numbers, click the insertion bar before the file number you previously typed in and hit return.\line Exit / Cmd-e\line Returns control to the Mac. Execution starts from the current value (which can be modified, of course, via the Regs window).\line Gosub / Cmd-g\line Same as Step (below), except that all JSR and BSR instructions are treated as a single instruction and the subroutine is called invisibly to you. In other words, this command executes exactly as if you had set a breakpoint immediately after the JSR or BSR and then exited. I often use this command the first time through a program to quickly find which JSR calls the subroutine that bombs. If you look at the Font/DA Mover listing above and condsider the Da Mover portion, imagine this as a protected program that Nosy won't handle. You are presented with several subroutines which you certainly don't want to spend valuable time tracing. So, you Gosub each one until you get a bomb. Then you know which one you need to spend time tracing.\line \'0CStep / Cmd-s\line Executes the instruction pointed to by the PC. This command allows you to execute a program one instruction at a time with one limitation (or boon) which is that traps are executed as if they were a single instruction. Use the Trace command to step through the actual ROM trap code. All windows that are affected by the executed instruction are updated automatically.\line Trace / Cmd-t\line Same as Step, except that ROM traps will be followed into their ROM code. You will never need to do this to crack a program, however if you want to see what a trap is really doing, use this command.\line Num / Cmd-n\line Brings up TMON's calculator. Any expression (almost) will be evaluated and displayed. For example, entering a trap name will return the trap number; entering a mathematical expression (or a number) will return the result in hex and decimal, etc. There are a million variations on this, non of which I have ever used, so if you have a question, get in touch with me for more info.\line User / Cmd-u\line This has a wealth of handy commands, but my desctiptions my descriptions will be limited to commands that I have used. There are three different screens associated with the User window: A000 trap functions, Control functions, and Memory functions. To switch pages, click on the line that reads Toggle Pages and press return until you arrive at the page you desire.\line \line Control Functions:\line Look for labels:\line Unknown.\line Label table\line Unknown.\line Label add/remove\line Unknown.\line Label file load\line Unknown.\line Registers\line Unknown. Has something to do with TMON's internal registers.\line Leave TMON: queue...\line Similar to Exit, except that TMON will trap out all events and regain control when you click the mouse. When TMON regains control, the previously generated events will be available in the event queue. To activate this function, click on the Leave TMON... line and press Return.\line Leave application...\line Use this function when your application system bombs. Using 0 as a parameter, attempts to quit to the active shell (usually the Finder), using 1 will attempt to re-launch the program. If you are in a program (not necessarily one you are cracking) and it system bombs, you will dive into the monitor. Use this function with a parameter of 0 and usually the app will quit to the Finder leaving any other open applications running normally.\line Shut Down\line If the above does not gracefully exit to the Finder, you may need to use this function. The higher the number of t}